/*
 *  \file WordNet.h
 *  WordNet
 *
 *  Created by Kutlak Roman on 28/08/2011.
 *  Copyright 2011 University of Aberdeen. All rights reserved.
 *
 */

#ifndef WordNet_h 
#define WordNet_h

#include <iostream>
#include <string>
#include <list>
#include <vector>

#include <wn.h>

#include "Utilities.h"

namespace kutlak {
namespace roman {
namespace gre {
    
    
    /*!
     * \brief A wrapper class for access to WordNet. 
     * 
     * #include <wn.h> <BR> 
     * -lwn
     * 
     */
    class WordNet { 
    public: 
        
#pragma mark -
#pragma mark lifecycle
        // No point in having multiple word net instances so use the singleton pattern.
        static WordNet& Instance();
        
        WordNet(const WordNet& from) = default;
        WordNet& operator=(const WordNet& from) = default;
        
        ~WordNet();
        
    private:
        WordNet();
        
    public:
#pragma mark -
#pragma mark operations
        /*! \brief Find synonyms for a particular word and POS.
         *  \param word the word for which we want synonyms.
         *  \param pos part of speech tag.
         *  \return set of synonyms.
         */
        StringVector_t Synonyms(const std::string& word, int pos);
        
        // all POS
        StringVector_t Synonyms(const std::string& word);
        
        //! \brief Method returns a list of synonyms for all words in a given set.
        StringVector_t Synonyms(const StringVector_t& words, int pos = NOUN);
        
        /*! \brief Find hypernyms for a particular word and POS.
         *  \param word the word for which we want hypernyms.
         *  \param pos part of speech tag, NOUN by default.
         *  \return set of hypernyms.
         */
        StringVector_t Hypernyms(const std::string& word, int pos = NOUN);
        
        
        /*! \brief Find antonyms for a particular word and POS.
         *  \param word the word for which we want antonym(s).
         *  \param pos part of speech tag.
         *  \return set of antonyms.
         */
        StringVector_t Antonyms(const std::string& word, int pos);
        
        // all POS
        StringVector_t Antonyms(const std::string& word);
        
        //! \brief Method returns a list of antonyms for all words in a given set.
        StringVector_t Antonyms(const StringVector_t& words, int pos = NOUN);
        
        /*! \brief Static method prints the nested list.
         *  \param words ResultT structure with words.
         *  \param indent number of tabs printed in front of each word, 1 by default.
         *  The method prints each word on a new line and inserts tabs
         *  in front of each word.
         */
        static void PrintWords(const StringVector_t& words, int indent = 1);
        
        /*! \brief Static method that takes the ResultT structure and returns it as a list
         *  \param words is the double nested list of wtrings.
         *  \param sense is the number of senses we want. The default value 0 returns all senses.
         *  \return list of words.
         *  Note that any word that appears more than once will only appear once in the final list.
         */
//        static SetT ResultToList(const ResultsetT& words, int senses = 0);
        
        int FindPos(const std::string& word);
    };
}
}
}
#endif // WordNet_h

///* Structure for data file synset */
//typedef struct ss {
//    long hereiam;		/* current file position */
//    int sstype;			/* type of ADJ synset */
//    int fnum;			/* file number that synset comes from */
//    char *pos;			/* part of speech */
//    int wcount;			/* number of words in synset */
//    char **words;		/* words in synset */
//    int *lexid;			/* unique id in lexicographer file */
//    int *wnsns;			/* sense number in wordnet */
//    int whichword;		/* which word in synset we're looking for */
//    int ptrcount;		/* number of pointers */
//    int *ptrtyp;		/* pointer types */
//    long *ptroff;		/* pointer offsets */
//    int *ppos;			/* pointer part of speech */
//    int *pto;			/* pointer 'to' fields */
//    int *pfrm;			/* pointer 'from' fields */
//    int fcount;			/* number of verb frames */
//    int *frmid;			/* frame numbers */
//    int *frmto;			/* frame 'to' fields */
//    char *defn;			/* synset gloss (definition) */
//    unsigned int key;		/* unique synset key */
//    
//    /* these fields are used if a data structure is returned
//     instead of a text buffer */
//    
//    struct ss *nextss;		/* ptr to next synset containing searchword */
//    struct ss *nextform;	/* ptr to list of synsets for alternate
//                             spelling of wordform */
//    int searchtype;		/* type of search performed */
//    struct ss *ptrlist;		/* ptr to synset list result of search */
//    char *headword;		/* if pos is "s", this is cluster head word */
//    short headsense;		/* sense number of headword */
//} Synset;
//
//typedef Synset *SynsetPtr;

//
//static struct {
//    char *option;		/* user's search request */
//    int search;			/* search to pass findtheinfo() */
//    int pos;			/* part-of-speech to pass findtheinfo() */
//    int helpmsgidx;		/* index into help message table */
//    char *label;		/* text for search header message */
//} *optptr, optlist[] = {
//    { "-synsa", SIMPTR,	ADJ, 0, "Similarity" },
//    { "-antsa", ANTPTR,	ADJ, 1, "Antonyms" },
//    { "-perta", PERTPTR, ADJ, 0, "Pertainyms" },
//    { "-attra", ATTRIBUTE, ADJ, 2, "Attributes" },
//    { "-domna", CLASSIFICATION, ADJ, 3, "Domain" },
//    { "-domta", CLASS, ADJ, 4, "Domain Terms" },
//    { "-famla", FREQ, ADJ, 5, "Familiarity" },
//    { "-grepa", WNGREP, ADJ, 6, "Grep" },
//    
//    { "-synsn", HYPERPTR, NOUN, 0, "Synonyms/Hypernyms (Ordered by Estimated Frequency)" },
//    { "-antsn", ANTPTR,	NOUN, 2, "Antonyms" },
//    { "-coorn", COORDS, NOUN, 3, "Coordinate Terms (sisters)" },
//    { "-hypen", -HYPERPTR, NOUN, 4, "Synonyms/Hypernyms (Ordered by Estimated Frequency)" },
//    { "-hypon", HYPOPTR, NOUN, 5, "Hyponyms" },
//    { "-treen", -HYPOPTR, NOUN, 6, "Hyponyms" },
//    { "-holon", HOLONYM, NOUN, 7, "Holonyms" },
//    { "-sprtn", ISPARTPTR, NOUN, 7, "Part Holonyms" },
//    { "-smemn", ISMEMBERPTR, NOUN, 7, "Member Holonyms" },
//    { "-ssubn", ISSTUFFPTR, NOUN, 7, "Substance Holonyms" },
//    { "-hholn",	-HHOLONYM, NOUN, 8, "Holonyms" },
//    { "-meron", MERONYM, NOUN, 9, "Meronyms" },
//    { "-subsn", HASSTUFFPTR, NOUN, 9, "Substance Meronyms" },
//    { "-partn", HASPARTPTR, NOUN, 9, "Part Meronyms" },
//    { "-membn", HASMEMBERPTR, NOUN, 9, "Member Meronyms" },
//    { "-hmern", -HMERONYM, NOUN, 10, "Meronyms" },
//    { "-nomnn", DERIVATION, NOUN, 11, "Derived Forms" },
//    { "-derin", DERIVATION, NOUN, 11, "Derived Forms" },
//    { "-domnn", CLASSIFICATION, NOUN, 13, "Domain" },
//    { "-domtn", CLASS, NOUN, 14, "Domain Terms" },
//    { "-attrn", ATTRIBUTE, NOUN, 12, "Attributes" },
//    { "-famln", FREQ, NOUN, 15, "Familiarity" },
//    { "-grepn", WNGREP, NOUN, 16, "Grep" },
//    
//    { "-synsv", HYPERPTR, VERB, 0, "Synonyms/Hypernyms (Ordered by Estimated Frequency)" },
//    { "-simsv", RELATIVES, VERB, 1, "Synonyms (Grouped by Similarity of Meaning)" },
//    { "-antsv", ANTPTR, VERB, 2, "Antonyms" },
//    { "-coorv", COORDS, VERB, 3, "Coordinate Terms (sisters)" },
//    { "-hypev", -HYPERPTR, VERB, 4, "Synonyms/Hypernyms (Ordered by Estimated Frequency)" },
//    { "-hypov", HYPOPTR, VERB, 5, "Troponyms (hyponyms)" },
//    { "-treev", -HYPOPTR, VERB, 5, "Troponyms (hyponyms)" },
//    { "-tropv", -HYPOPTR, VERB, 5, "Troponyms (hyponyms)" },
//    { "-entav", ENTAILPTR, VERB, 6, "Entailment" },
//    { "-causv", CAUSETO, VERB, 7, "\'Cause To\'" },
//    { "-nomnv", DERIVATION, VERB, 8, "Derived Forms" },
//    { "-deriv", DERIVATION, VERB, 8, "Derived Forms" },
//    { "-domnv", CLASSIFICATION, VERB, 10, "Domain" },
//    { "-domtv", CLASS, VERB, 11, "Domain Terms" },
//    { "-framv", FRAMES, VERB, 9, "Sample Sentences" },
//    { "-famlv", FREQ, VERB, 12, "Familiarity" },
//    { "-grepv", WNGREP, VERB, 13, "Grep" },
//    
//    { "-synsr", SYNS, ADV, 0, "Synonyms" },
//    { "-antsr", ANTPTR, ADV, 1, "Antonyms" },
//    { "-pertr", PERTPTR, ADV, 0, "Pertainyms" },
//    { "-domnr", CLASSIFICATION, ADV, 2, "Domain" },
//    { "-domtr", CLASS, ADV, 3, "Domain Terms" },
//    { "-famlr", FREQ, ADV, 4, "Familiarity" },
//    { "-grepr", WNGREP, ADV, 5, "Grep" },
//    
//    { "-over", OVERVIEW, ALL_POS, -1, "Overview" },
//    { NULL, 0, 0, 0, NULL }
//};





